// Hacer las importaciones.
import java.io.{File};
import scala.util.matching.Regex;
import scala.collection.mutable.Queue;
import scala.actors.Actor;
import scala.actors._;

object sistema extends Actor {
	
	// Declarar variables y objetos de instancia
	private var procesos : Queue[Proceso] = new Queue();
  	private var archivosAbiertos : List[File] = Nil;
  	private var id_counter : Int = 0;
  	private var proceso_actual : Proceso = null;
   	private var registros : Array[Int] = new Array[Int](8);
   	object salir {}
    

	/*
	*/
	def act() = {
	  while(true) {
	    receive {
	      case s : String => {
	        while(true) {
	          // Realizar mientras haya procesos en estado Ready.
	          //println(procesos.size);
	          if(!procesos.isEmpty) {
	            //println("++++++++++++++++++++++++++++++++++++++++Hay procesos");
	            // Ejecutar un tic
	            proceso_actual = procesos dequeue; 
	            ejecutarTic();
	            
	            // Realizar context switch
	            contextSwitch();
	            //println("------------------salir?");
	          };
	        }
	      }
	    }
	  }
	}
  
	/**
	*/
	def nuevoProceso(comando : String) : Any = {
		// Cread el pid del proceso
		id_counter += 1;
		// Crear el nuevo proceso sincronico
		val proceso : Proceso = new Proceso(null, comando, id_counter);
		
		// Agregarlo a la cola de 
		procesos += proceso;
		proceso configurar;
		
		// Determinar si el proceso es síncrono o asíncrono
		if(proceso isSincrono) {
			// Si es sincrono
			
			// Mantener el proceso hasta que el proceso de halla terminado
			while (proceso.getEstado() != proceso.TERMINATED) {
			  
			}
	    
			// Devolver el estado del proceso.
			proceso.resultado;
		} else {
		  // Si no es síncrono no devolver nada.
		  null;
		}
   	}
 
	/**
	 *  
	 */
	def ejecutarTic() = {
   		//case "open" => logger io "Ejecutar 'open'.";
	  //println("interprete");
	}
  
   	/**
     * 
     */
   	private def contextSwitch() = {
   	  // Verificar el proceso actual
      if((proceso_actual != null) 
         && (!proceso_actual.isCloseble)) {
          procesos enqueue proceso_actual;
   	  }
      proceso_actual = null;
       
      //println("hola");
      
      // Llevar al siguiente proceso
      var seguir = true;
      while(!procesos.isEmpty && seguir) {
    	var list = procesos clone;
    	var sig = list dequeue;
  	  	//println(sig);
   	    sig match {
	   	  	case p if (p.getEstado == p.READY) => {
	   	  	  seguir = false
	        } case p if(!p.isCloseble) => {
	          procesos dequeue;
	        } case _ => {
	        }
   	    }
   	  }
      //println("adios");
   	} 
  
  /**
   * 
   */
  def fork(proceso : Proceso, comando : String) : Unit = {
    id_counter += 1;
    this.procesos += new Proceso(proceso, comando, id_counter);
  }
  
  /**
   * 
  */
  def ps() : String = {
    var resp = "PID\t(s) Program\n";
    
    procesos foreach { s =>
    	resp +=  s + "\n"
    }
    
    resp
  }
  
  
  def kill(pid : Int) = {
    procesos foreach { s =>
    	if(s.getPid == pid) {
    	  s.terminar()
    	}
    }
  }
}
